import { unByKey } from 'ol/Observable';
import { fromLonLat } from 'ol/proj';
import * as echarts from 'echarts';
/**
 * 飞线图类，用于在OpenLayers地图上展示ECharts飞线效果
 */
export class FlyLine {
    /**
     * 构造函数
     * @param map OpenLayers地图实例
     * @param option 飞线图配置选项
     */
    constructor(map, option) {
        /** OpenLayers地图实例 */
        Object.defineProperty(this, "map", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /** ECharts实例 */
        Object.defineProperty(this, "echarts", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /** 父级DOM元素 */
        Object.defineProperty(this, "parentDom", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /** 是否可见 */
        Object.defineProperty(this, "visible", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /** ECharts图表配置 */
        Object.defineProperty(this, "chartOption", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /** 容器DOM元素 */
        Object.defineProperty(this, "box", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /** ECharts图表实例 */
        Object.defineProperty(this, "chart", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /** 地图事件监听器1 */
        Object.defineProperty(this, "extentWatch1", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: []
        });
        /** 地图事件监听器2 */
        Object.defineProperty(this, "extentWatch2", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: []
        });
        this.removeLayer();
        // 如果在服务器上使用该代码 可以将echart对象传入到option中
        this.echarts = echarts;
        if (option.visible === undefined) {
            this.visible = true;
        }
        else {
            this.visible = option.visible;
        }
        this.map = map;
        this.parentDom = option.parentDom;
        this.box = null;
        this.echarts.registerCoordinateSystem('openlayers', this.getE3CoordinateSystem(map));
        this.init(map);
    }
    /**
     * 初始化飞线图
     * @param map OpenLayers地图实例
     */
    init(map) {
        this.setBaseMap(map);
        this.createLayer();
    }
    /**
     * 设置基础地图
     * @param map OpenLayers地图实例
     */
    setBaseMap(map) {
        this.map = map;
    }
    /**
     * 设置图表配置
     * @param option ECharts配置选项
     */
    setChartOption(option) {
        this.chartOption = option;
        this.setCharts();
    }
    /**
     * 设置可见性
     * @param bool 是否可见
     */
    setVisible(bool) {
        if (!this.box || this.visible === bool)
            return;
        this.box.hidden = !bool;
        this.visible = bool;
        bool === true && this.setCharts();
    }
    /**
     * 开始刷新
     */
    refreshBegin() {
        if (this.box) {
            this.box.hidden = true;
        }
    }
    /**
     * 刷新中
     */
    refreshing() {
        this.setCharts();
    }
    /**
     * 刷新结束
     */
    refreshEnd() {
        if (this.box) {
            this.box.hidden = false;
        }
    }
    /**
     * 绑定事件
     * @param eventName 事件名称
     * @param handler 事件处理函数
     * @param context 上下文
     */
    on(eventName, handler, context) {
        this.chart.on(eventName, handler, context);
    }
    /**
     * 解绑事件
     * @param eventName 事件名称
     * @param handler 事件处理函数
     * @param context 上下文
     */
    off(eventName, handler, context) {
        this.chart.off(eventName, handler, context);
    }
    /**
     * 设置图表
     */
    setCharts() {
        if (!this.visible)
            return;
        if (this.chartOption == null || this.chartOption === 'undefined')
            return;
        var baseExtent = this.map.getView().getViewStateAndExtent().extent;
        // 判断是否使用了mark类型标签，每次重绘要重新转换地理坐标到屏幕坐标
        // 根据地图extent,重绘echarts
        if (baseExtent) {
            this.chartOption.xAxis = { show: false, min: baseExtent[0], max: baseExtent[2] };
            this.chartOption.yAxis = { show: false, min: baseExtent[1], max: baseExtent[3] };
            this.chart.setOption(this.chartOption);
            this.chartOption.animation = false;
        }
        if (this.box) {
            const size = this.map.getSize();
            if (size) {
                this.box.style.width = size[0] + 'px';
                this.box.style.height = size[1] + 'px';
            }
        }
    }
    /**
     * 创建图层容器
     */
    createLayer() {
        var box = (this.box = document.createElement('div'));
        box.setAttribute('id', 'echartsData');
        box.setAttribute('name', 'echartsData');
        const size = this.map.getSize();
        if (size) {
            box.style.width = size[0] + 'px';
            box.style.height = size[1] + 'px';
        }
        box.style.position = 'absolute';
        box.style.top = '0';
        box.style.left = '0';
        this.box = box;
        if (this.parentDom) {
            this.parentDom.appendChild(box);
        }
        else {
            var parent_1 = document.getElementsByClassName('ol-viewport')[0];
            parent_1.appendChild(box);
        }
        this.chart = this.echarts.init(box);
        this.startMapEventListeners();
    }
    /**
     * 移除图层
     */
    removeLayer() {
        this.visible = false;
        this.extentWatch1 && unByKey(this.extentWatch1);
        this.extentWatch2 && unByKey(this.extentWatch2);
        if (this.box) {
            this.box.outerHTML = '';
        }
        this.box = null;
        this.chart && this.chart.dispose();
        this.chart = null;
        this.chartOption = null;
    }
    /**
     * 开始地图事件监听
     */
    startMapEventListeners() {
        var map = this.map;
        this.extentWatch1 = map.on('movestart', () => {
            if (this.box)
                this.box.hidden = true;
        });
        this.extentWatch2 = map.on('moveend', () => {
            if (!this.visible)
                return;
            this.setCharts();
            this.chart.resize();
            if (this.box)
                this.box.hidden = false;
        });
    }
    /**
     * 获取ECharts坐标系统
     * @param map OpenLayers地图实例
     * @returns ECharts坐标系统
     */
    getE3CoordinateSystem(map) {
        var CoordSystem = function CoordSystem(map) {
            this.map = map;
            this._mapOffset = [0, 0];
        };
        CoordSystem.prototype.create = function (ecModel) {
            ecModel.eachSeries(function (seriesModel) {
                if (seriesModel.get('coordinateSystem') === 'openlayers') {
                    seriesModel.coordinateSystem = new CoordSystem(map);
                }
            });
        };
        CoordSystem.prototype.getDimensionsInfo = function () {
            return ['x', 'y'];
        };
        CoordSystem.prototype.dimensions = ['x', 'y'];
        CoordSystem.prototype.setMapOffset = function setMapOffset(mapOffset) {
            this._mapOffset = mapOffset;
        };
        CoordSystem.prototype.dataToPoint = function dataToPoint(data) {
            var projectionCode = this.map.getView().getProjection().getCode();
            var point = [data[0], data[1]];
            if (projectionCode === 'EPSG:3857') {
                point = fromLonLat(point); // 转为3857
            }
            var px = map.getPixelFromCoordinate(point);
            var mapOffset = this._mapOffset;
            return [px[0] - mapOffset[0], px[1] - mapOffset[1]];
        };
        CoordSystem.prototype.pointToData = function pointToData(pt) {
            var mapOffset = this._mapOffset;
            var screentPoint = [pt[0] + mapOffset[0], pt[1] + mapOffset[1]];
            var data = map.getCoordinateFromPixel(screentPoint);
            return [data[0], data[1]];
        };
        CoordSystem.prototype.getViewRect = function getViewRect() {
            // return new graphic.BoundingRect(0, 0, this.map.getSize()[0], this.map.getSize()[1])
        };
        CoordSystem.prototype.getRoamTransform = function getRoamTransform() {
            // return matrix.create()
        };
        return CoordSystem;
    }
}
